-- RotineActivityM
-- Created by cheny3 Nov/10/2016
-- 常规活动模块

module("RotineActivityM", package.seeall);

local PURE_FILE = "RotineActivityM";

-- 子规则模块
local rules = {};

-- 配置表
local bonusTable = {};
local taskTable = {};
local typeRules = {};
local ruleTask = {};

-- 载入配置表
local _init = false;
local loadCsv = function()
    if _init then return end
    _init = true;

    -- 载入子规则
    rules = LOAD_PATH("game/logic/module/rotine_activity");

    -- 载入任务配置表
    taskTable = {};
    local rotine_activity_task_CSV = get_rotine_activity_task_CSV();
    for i = 1, #rotine_activity_task_CSV do
        local id = rotine_activity_task_CSV[i].id;
        taskTable[id] = rotine_activity_task_CSV[i];

        -- 整理
        local info = taskTable[id];
        local taskType = info["type"];
        local taskRule = info["rule"];

        -- 某类型全部规则
        local arr = typeRules[taskType] or {};
        if table.indexOf(arr, taskRule) < 0 then
            table.insert(arr, taskRule);
            typeRules[taskType] = arr;
        end

        -- 某规则全部任务
        arr = ruleTask[taskRule] or {};
        if table.indexOf(arr, id) < 0 then
            table.insert(arr, id);
            ruleTask[taskRule] = arr;
        end
    end
    rotine_activity_task_CSV = nil;

    -- 载入奖励配置表
    bonusTable = {};
    local rotine_activity_bonus_CSV = get_rotine_activity_bonus_CSV();
    for i = 1, #rotine_activity_bonus_CSV do
        local id = rotine_activity_bonus_CSV[i].id;
        bonusTable[id] = rotine_activity_bonus_CSV[i];
    end
    rotine_activity_bonus_CSV = nil;
end

-- 模块初始化
function init()
    -- 载入活动配置表
    loadCsv();
end

-- 检索活动任务配置
function queryTask(id, path)
    if not taskTable[id] then
        return nil;
    end

    if path == nil or path == "" then
        return taskTable[id];
    end

    return taskTable[id][path];
end

-- 检索活动奖励配置
function queryBonus(id, path)
    if not bonusTable[id] then
        return nil;
    end

    if path == nil or path == "" then
        return bonusTable[id];
    end

    return bonusTable[id][path];
end

-- 当前常规活动的活动ID
function getCurRotineActivityId()
    local activitys = table.keys(ActivityM.getCurrentActivities());
    for _, id in pairs(activitys) do
        local status = ActivityM.getActivityStatus(ActivityM.getActivityInfo(id));
        local activityType = ActivityM.query(id, "type");
        if activityType == ACTIVITY_TYPE_ROTINE and status == ACTIVITY_STATUS_START then
            return id;
        end
    end

    return 0;
end

-- 当前是否在常规活动中
function isInRotineActivity()
    if ServerStatusM.query(MODULE_SWITCH_FORBID_ROUTINE_ACTIVITY) == 1 then
        return false;
    end

    return getCurRotineActivityId() > 0;
end

-- 常规活动信息
function getRotineInfo()
    local id = getCurRotineActivityId();
    if id <= 0 then
        return {};
    end

    return ActivityM.getActivityInfo(id);
end

-- 常规活动是否允许显示
function isRotineOpen()
    -- 如果还未通关5-2
    if not DungeonAreaM.isDungeonPassed(ME.user, 52) then
        return false;
    end

    return true;
end

-- 当前主地图是否需要提示
function needToTip()
    local info = getUserRotineInfo();
    local taskInfo = info["rotine_tasks"] or {};
    for taskRule, ruleInfo in pairs(taskInfo) do
        -- 有可以领取的进度
        if calcProgressBonusId(taskRule, ruleInfo) > 0 then
            return true;
        end
    end

    if canBonus() then
        -- 有可以兑换的
        return true;
    end

    return false;
end

-- 当前可以领取的进度奖励
function calcProgressBonusId(rule, info)
    local bonusProgress = info["bonus_progress"];
    local curProgress = bonusProgress + 1;

    local tasks = getAllTasksByRule(rule);
    for _, id in pairs(tasks) do
        local taskInfo = queryTask(id);
        if taskInfo["progress"] == curProgress and
            info["value"] >= taskInfo["require"] then
            -- 是下一个进度，并且数值足够
            return id;
        end
    end
    return 0;
end

-- 玩家的活动信息
function getUserRotineInfo()
    return ME.user.dbase:query("rotine_activity_info", {});
end

-- 获取某个类型的所有任务ID
function getAllTasksByRule(taskRule)
    local ret = ruleTask[taskRule] or {};
    table.sort(ret);
    return ret;
end

-- 获取某个类型的所有规则
function getAllRulesByType(taskType)
    local ret = typeRules[taskType];
    table.sort(ret);
    return ret;
end

-- 某任务当前情况
function getUserTaskInfo(taskRule)
    local info = getUserRotineInfo();
    local taskInfo = (info["rotine_tasks"] or {})[taskRule];
    if not taskInfo then
        return {};
    end

    -- 当前完成进度
    local progress = 0;
    local value = taskInfo["value"];
    local allTasks = getAllTasksByRule(taskRule);
    for _, id in pairs(allTasks) do
        if value >= queryTask(id, "require") then
            progress = progress + 1;
        end
    end

    local ret = {
        ["curProgress"]   = progress,       -- 当前进度
        ["totalProgress"] = #allTasks,      -- 总进度
        ["value"]          = value,         -- 完成数值
        ["bonusProgress"] = taskInfo["bonus_progress"],  -- 领奖进度
    };

    return ret;
end

-- 获得某任务的奖励信息
function getTotalBonusCount(taskRule)
    local info = getUserRotineInfo();
    local rotineType = info["rotine_type"];

    local attrib;
    local value = 0;
    local tasks = getAllTasksByRule(taskRule);
    for _, id in pairs(tasks) do
        local bonus = queryTask(id, "bonus")[rotineType];
        attrib = bonus[1];
        value = value + bonus[2];
    end

    return {attrib, value};
end

-- 获得某个任务的奖励信息
function getTaskBonusCount(taskId)
    local info = getUserRotineInfo();
    local rotineType = info["rotine_type"];

    local bonus = queryTask(taskId, "bonus")[rotineType];
    local attrib = bonus[1];
    local value = bonus[2];
    return {attrib, value};
end

-- 当前是否可以领取某个类型的进度奖励
function canTakeProgressBonus(taskRule)
    if not isInRotineActivity() then
        return false;
    end

    local info = getUserRotineInfo();
    local taskInfo = info["rotine_tasks"] or {};
    local ruleInfo = taskInfo[taskRule];
    if not ruleInfo then
        return false;
    end

    -- 当前没有可以领取的
    if calcProgressBonusId(taskRule, ruleInfo) <= 0 then
        return false;
    end

    return true;
end

-- 领取进度奖励
function takeProgerssBonus(taskRule)
    if true ~= canTakeProgressBonus(taskRule) then
        return false;
    end

    Operation.cmd_rotine_take_progress_bonus(taskRule);
    return true;
end

-- 是否已经兑换
function isExchangeAlready(index)
    local info = getUserRotineInfo();
    if info["rotine_type"] ~= "score" then
        return false;
    end

    local bonus = info["rotine_bonus"] or {};
    local bonusInfo = bonus[index];

    if not bonusInfo then
        return false;
    end

    if bonusInfo["sold_out"] ~= 1 then
        return false;
    end

    return true;
end

-- 能否兑换
function canExchangeBonus(index)
    if not isInRotineActivity() then
        return false;
    end

    local info = getUserRotineInfo();
    if info["rotine_type"] ~= "score" then
        return false;
    end

    local bonus = info["rotine_bonus"] or {};
    local bonusInfo = bonus[index];

    if not bonusInfo then
        return false;
    end

    if isExchangeAlready(index) then
        return "sold_out";
    end

    local bonusId = bonusInfo["id"];
    local price = queryBonus(bonusId, "price");
    local cost = price[info["rotine_type"]];

    if info[cost[1]] < cost[2] then
        return "lack_item";
    end

    return true;
end

-- 兑换奖励
function exchangeBonus(index)
    if true ~= canExchangeBonus(index) then
        return false;
    end

    Operation.cmd_rotine_exchange_bonus(index);
    return true;
end

-- 对应位置的奖励
function getTreasureBonus(index)
    local ret = {};

    local info = getUserRotineInfo();
    local bonus = info["rotine_bonus"] or {};
    local bonusInfo = bonus[index];

    if not bonusInfo then
        return {};
    end

    -- TODO 暂时认为奖励只有1个
    return bonusInfo["bonus"][1];
end

-- 是否已经领奖
function isTreasureTaked(index)
    local info = getUserRotineInfo();
    local bonusType = info["rotine_type"];
    if bonusType ~= "treasure" then
        return false;
    end

    local bonus = info["rotine_bonus"] or {};
    local bonusInfo = bonus[index];

    if not bonusInfo then
        return false;
    end

    if bonusInfo["take_bonus"] ~= 1 then
        return false;
    end

    return true;
end

-- 能否挖宝
function canUserTakeTreasure(index)
    if not isInRotineActivity() then
        return false;
    end

    local info = getUserRotineInfo();
    local bonusType = info["rotine_type"];
    if bonusType ~= "treasure" then
        return false;
    end

    local bonus = info["rotine_bonus"] or {};
    local bonusInfo = bonus[index];

    if not bonusInfo then
        return false;
    end

    if not isTreasureOpened(index) then
        -- 还没有翻开过
        return false;
    end

    if isTreasureTaked(index) then
        -- 已经领取了
        return false;
    end

    return true;
end

-- 挖宝
function takeTreasure(index)
    if true ~= canUserTakeTreasure(index) then
        return false;
    end

    Operation.cmd_rotine_take_treasure(index);
    return true;
end

-- 是否已经挖宝
function isTreasureOpened(index)
    local info = getUserRotineInfo();
    local bonusType = info["rotine_type"];
    if bonusType ~= "treasure" then
        return false;
    end

    local bonus = info["rotine_bonus"] or {};
    local bonusInfo = bonus[index];

    if not bonusInfo then
        return false;
    end

    if bonusInfo["opened"] ~= 1 then
        return false;
    end

    return true;
end

-- 能否挖宝
function canUserOpenTreasure(index)
    if not isInRotineActivity() then
        return false;
    end

    local info = getUserRotineInfo();
    local bonusType = info["rotine_type"];
    if bonusType ~= "treasure" then
        return false;
    end

    local bonus = info["rotine_bonus"] or {};
    local bonusInfo = bonus[index];

    if not bonusInfo then
        return false;
    end

    if isTreasureOpened(index) then
        -- 已经翻开了
        return false;
    end

    if isTreasureTaked(index) then
        -- 已经领过了
        return false;
    end

    local bonusId = bonusInfo["id"];
    local price = queryBonus(bonusId, "price");
    local cost = price[info["rotine_type"]];

    if info[cost[1]] < cost[2] then
        return "lack_item";
    end

    return true;
end

-- 挖宝
function openTreasure(index)
    if true ~= canUserOpenTreasure(index) then
        return false;
    end

    Operation.cmd_rotine_open_treasure(index);
    return true;
end

-- 当前属性类型
function getAttribInfo()
    local info = getUserRotineInfo();
    if info["rotine_type"] == "treasure" then
        -- 挖宝
        return {"rotine_hoe", tonumber(info["rotine_hoe"])};
    else
        -- 代币
        return {"rotine_score", tonumber(info["rotine_score"])};
    end
end

-- 查询技能规则
function queryRule(rule)
    if rules[rule] == "TBL" then
        return LOAD_RUN("game/logic/module/rotine_activity/" .. rule);
    end

    return rules[rule];
end

-- 当前这个规则的任务玩家能否显示
function canUserShowTask(taskRule)
    local ruleObject = queryRule(taskRule);
    if ruleObject and ruleObject.canUserShowTask then
        -- 有子规则的用子规则
        return ruleObject.canUserShowTask();
    end

    return true;
end

-- 当前有可以挖宝/兑换的
function canBonus()
    local info = RotineActivityM.getUserRotineInfo();
    local rotineType = info["rotine_type"];
    if rotineType == "treasure" then
        -- 挖宝，有铲子就提示
        return tonumber(info["rotine_hoe"]) > 0;
    else
        -- 兑换，有可以兑换的
        local bonus = info["rotine_bonus"];
        for _, index in ipairs(table.keys(bonus)) do
            if true == canExchangeBonus(index) then
                return true;
            end
        end
    end

    return false;
end